package com.qike.duola.shiro.jwt;

import com.qike.duola.mapper.SysResourceMapper;
import com.qike.duola.domain.SysResource;
import com.qike.duola.domain.SysUser;
import com.qike.duola.mapper.SysUserMapper;
import com.qike.duola.utils.TokenUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.util.*;

@Component
public class JwtRealm extends AuthorizingRealm {

    @Autowired
    private TokenUtil tokenUtil;
    @Resource
    private SysResourceMapper sysMenuMapper ;
    @Resource
    private SysUserMapper sysUserMapper ;

    @Override
    public boolean supports(AuthenticationToken token) {
        //表示此Realm只支持JwtToken类型
        return token instanceof JwtToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        List<String> permsList;
        // 根据用户名查找角色，请根据需求实现
        Long userId = (Long)principals.getPrimaryPrincipal();
        //根据用户id查询用户角色
//        List<SysResource> sysResources = sysMenuMapper.selectByExample(new SysResourceExample());
        List<SysResource> menuList = sysMenuMapper.selectList(userId);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        permsList = new ArrayList<>(menuList.size());
        for(SysResource menu : menuList){
            permsList.add(menu.getPermission());
        }
        //用户权限列表
        Set<String> permsSet = new HashSet<>();
        for(String perms : permsList){
            if(StringUtils.isEmpty(perms)){
                continue;
            }
            permsSet.addAll(Arrays.asList(perms.trim().split(",")));
        }
        // 根据username查询角色
//        authorizationInfo.setRoles(Sets.newHashSet("admin","superadmin"));

        // 根据username查询权限
//        authorizationInfo.setStringPermissions(Sets.newHashSet("system:*"));
        authorizationInfo.setStringPermissions(permsSet);

        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        JwtToken jwtToken = (JwtToken) authenticationToken;

        // 获取token
        String token = jwtToken.getToken();

        // 从token中获取用户名
        Long username = Long.valueOf(tokenUtil.getUsernameFromToken(token));

        // 根据用户名查询数据库
        SysUser user = sysUserMapper.selectByPrimaryKey(username);

//        SysUser user = new SysUser();
//        user.setUserName(username);
//        user.setStatus(1);
//        user.setPassword("000000");

        // 用户不存在
        if (user == null) {
            throw new UnknownAccountException();
        }

        // 用户被禁用
        if(user.getStatus()==0){
            throw new LockedAccountException();
        }

        try {
            return new SimpleAuthenticationInfo(
                    username,
                    token,
                    getName()
            );
        } catch (Exception e) {
            throw new AuthenticationException(e);
        }
    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

}
